package com.com.effectivejava.commonmethods.hashcode;

import java.util.Objects;
import java.util.logging.Logger;

/**
 * Created by User on 14/07/2014.
 */
public class HashCodeJB {
    static Logger logger = Logger.getLogger(HashCodeJB.class.getName());

    static {
        logger.setParent(Logger.getLogger(HashCodeJB.class.getPackage().getName()));
    }

    protected boolean b = true;

    protected char c;
    protected byte bt;
    protected short s;
    protected int i;
    protected long l;

    protected float f;
    protected double d;

    protected String st;

    public HashCodeJB(boolean b, char c, byte bt, short s, int i, long l, float f, double d, String st) {
        Objects.requireNonNull(st, "Argument string should not be null !!!");
        this.b = b;
        this.c = c;
        this.bt = bt;
        this.s = s;
        this.i = i;
        this.l = l;
        this.f = f;
        this.d = d;
        this.st = st;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("HashCodeJB {");
        builder.append(" b(boolean): " + b);
        builder.append(" ,c(character): " + c);
        builder.append(" ,bt(byte): " + bt);
        builder.append(" ,s(short): " + s);
        builder.append(" ,i(int): " + i);
        builder.append(" ,l(long): " + l);
        builder.append(" ,f(float): " + f);
        builder.append(" ,d(double): " + d);
        builder.append(" ,st(String): " + st.toString());
        builder.append(" , HASHCODE: " + this.hashCode());
        builder.append(" }");

        return builder.toString();
    }

    //As per JB.
    @Override
    public boolean equals(Object o) {
        if (this == o)
            return true;

        // Takes care of Null pointer in-case o is null
        // if left operand of instanceOf is null, acc to
        // instanceOf specification, it returns false.

        if (!(o instanceof HashCodeJB))
            return false;

        HashCodeJB e = (HashCodeJB) o;
        return isThis(e);
    }

    private boolean isThis(HashCodeJB e) {
        return (b == e.b)
                && (c == e.c)
                && (bt == e.bt)
                && (s == e.s)
                && (i == e.i)
                && (l == e.l)
                && (Float.compare(f, e.f) == 0)
                && (Double.compare(d, e.d) == 0)
                && (st.equals(e.st));
    }

    /* complete(fairly efficient) hashCode as per JB*/
    @Override
    public int hashCode() {
        int result = 17;
        result = 31 * result + (b ? 0 : 1);

        result = result + (int) c;
        result = 31 * result + (int) bt;
        result = 31 * result + (int) s;
        result = 31 * result + i;
        result = 31 * result + (int) (l ^ (l >>> 32));

        result = result + Float.floatToIntBits(f);
        long temp = Double.doubleToLongBits(d);
        result = result + result + (int) (temp ^ (temp >>> 32));

        result = result + st.hashCode();
        return result;
        //return super.hashCode();
    }
}


